UI/UX 设计语言系统
设计语言系统(Design Language System,DLS)是一套完整的设计标准,旨在通过可复用的组件和模式来大规模管理设计。它将品牌、设计规范和代码实现统一为一个有凝聚力的生态系统,使设计师和开发者能够高效、一致地构建数字产品。
1. 概述
1.1 DLS 五层模型
一个成熟的设计语言系统通常在以下层面产生价值:
- 效率与速度:减少重复造轮子,加速设计与开发流程
- 一致性:确保产品在视觉和交互上保持统一品牌体验
- 跨职能协作:建立设计师与开发者之间的统一语言
- 可扩展性:支持产品从单一应用到多产品生态的规模化演进
- 降低维护成本:主题切换、品牌升级只需更新 Design Token 即可全局生效
| 层级 | 内容 | 典型产物 |
|---|---|---|
| 设计理念 | 品牌价值观、设计原则、可访问性标准 | Design Principles、Brand Guidelines |
| Design Tokens | 颜色、间距、字体、阴影等原子级设计决策 | tokens.json、CSS Variables、Sass Maps |
| 组件 | Button、Input、Card、Modal 等可复用 UI 单元 | React/Vue 组件、Figma Variants |
| 模式 | 表单页、列表页、详情页等可复用页面布局 | Page Templates、Layout Presets |
| 文档 | 使用指南、代码示例、设计规范 | Storybook、Zeroheight、Docusaurus |
1.2 主流设计流程规范
在动手搭建 DLS 之前,必须先理解业界公认的 UI/UX 设计流程框架。以下四套方法论是当今互联网和软件行业最广泛采用的设计流程标准。
Double Diamond(双钻模型)— 英国设计委员会
最具影响力的设计流程框架之一,将设计过程分为四个阶段,两次「发散—收敛」循环,形态如两颗钻石。
| 阶段 | 动作 | 核心产出 |
|---|---|---|
| Discover 发现 | 用户研究、竞品分析、利益相关者访谈 | 用户画像、旅程地图、问题陈述 |
| Define 定义 | 综合研究发现,收敛为清晰的问题定义 | 设计简报(Design Brief)、HMW 问题 |
| Develop 开发 | 头脑风暴、草图、低保真原型、多方案迭代 | 线框图、交互原型、A/B 方案 |
| Deliver 交付 | 高保真设计、用户测试、最终验收 | 高保真 Mockup、设计标注、开发 Spec |
Design Thinking(设计思维)— IDEO / Stanford d.school
以人为中心的设计方法论,强调同理心和快速迭代,广泛用于产品创新和数字化转型项目。
| 阶段 | 核心问题 | 常用方法 |
|---|---|---|
| Empathize 共情 | 用户真正需要什么? | 用户访谈、影子观察、沉浸式体验 |
| Define 定义 | 核心问题是什么? | 亲和图、POV 陈述、用户故事 |
| Ideate 构思 | 有哪些可能的解决方案? | 头脑风暴、疯狂八分钟、SCAMPER |
| Prototype 原型 | 如何快速验证想法? | 纸质原型、可交互原型、Wizard of Oz |
| Test 测试 | 方案是否有效?如何改进? | 可用性测试、A/B 测试、启发式评估 |
Google Design Sprint — Google Ventures
5 天快速验证产品方向的紧凑流程,适合新功能或新产品从零到一的场景。
| Day | 主题 | 活动 |
|---|---|---|
| 周一 | Map 绘制地图 | 定义长期目标、绘制用户旅程、选择焦点 |
| 周二 | Sketch 草图发散 | 竞品闪电演示、个人方案草图 |
| 周三 | Decide 决策 | 投票选出最优方案、绘制故事板 |
| 周四 | Prototype 原型 | 搭建可交互的高保真原型 |
| 周五 | Test 测试 | 与 5 名真实用户进行可用性测试 |
User-Centered Design(以用户为中心的设计)— ISO 9241-210
国际标准化组织定义的交互系统人因工程标准,是所有设计流程的底层哲学基础。
| 原则 | 含义 | 在 DLS 中的体现 |
|---|---|---|
| 基于用户、任务和环境的明确理解 | 设计决策必须有用户数据支撑 | Color Token 命名考虑色觉障碍用户(WCAG 对比度 ≥ 4.5:1) |
| 用户全程参与设计与开发 | 从需求到验收用户持续介入 | 组件库发布前执行可用性测试,收集开发者使用反馈 |
| 通过用户反馈驱动与迭代设计 | 设计是循环迭代过程 | Storybook 集成 Chromatic 视觉回归测试,每个版本收集 Analytics |
| 设计面向整体用户体验 | 考虑视觉、交互、情感、可访问性 | Token 覆盖颜色/间距/动效/声音,组件覆盖 loading/empty/error 状态 |
| 设计团队包含多学科技能和视角 | 设计师+开发者+PM+用户研究 | Design Token 采用 DTCG 规范,设计师在 Figma 与开发者在代码中使用同一套变量名 |
流程规范与 DLS 的映射关系
一个 DLS 项目的完整落地路径,自然对应上述流程的不同阶段:
| DLS 建设阶段 | 对应流程 | 关键产物 |
|---|---|---|
| 品牌与设计原则确立 | Double Diamond (Discover + Define) | Design Principles 文档、品牌色板 |
| Design Token 体系设计 | Design Thinking (Empathize + Define) | Token 命名规范、Global/Alias/Component 三层架构 |
| 组件库 MVP 构建 | Design Sprint (Sketch + Prototype) | 核心组件 (Button/Input/Table/Modal) 代码实现 |
| 文档站与使用指南 | ISO 9241-210 (用户参与) | Storybook / Zeroheight + 快速入门指南 |
| 迭代与维护 | Design Thinking (Test → 循环) | 版本 CHANGELOG、组件使用统计、定期 Review |
2. 行为图(系统"做什么")
从用户角色与工作流的角度,描述设计语言系统在生产环境中的运转方式。
2.1 用例图 —— 参与者与使用场景
设计语言系统的核心参与者包括设计师、前端开发者、产品经理和品牌团队。每个角色在系统中有不同的关注点和操作。
2.2 活动图 —— 设计系统构建与消费流程
从 Foundation 层的 Design Token 定义开始,逐层构建到 Component、Pattern,最终被设计师与开发者消费。
Demo — Style Dictionary 配置示例:下方展示了如何用 Style Dictionary 将一份 token 定义转换为多平台输出。
// tokens/color.json
{
"color": {
"primary": { "value": "#1677ff" },
"success": { "value": "#52c41a" },
"warning": { "value": "#faad14" },
"danger": { "value": "#ff4d4f" }
}
}
// config.js —— Style Dictionary 配置
const StyleDictionary = require('style-dictionary');
StyleDictionary.extend({
source: ['tokens/**/*.json'],
platforms: {
css: {
transformGroup: 'css',
buildPath: 'dist/',
files: [{ destination: 'variables.css', format: 'css/variables' }]
},
scss: {
transformGroup: 'scss',
buildPath: 'dist/',
files: [{ destination: 'variables.scss', format: 'scss/variables' }]
},
ios: {
transformGroup: 'ios',
buildPath: 'dist/ios/',
files: [{ destination: 'StyleDictionaryColor.h', format: 'ios/colors.h' }]
}
}
}).buildAllPlatforms();
2.3 序列图 —— 从 Design Token 到最终 UI 的渲染管线
一条设计决策如何在设计工具中产生,通过 Token 系统编译,注入组件库,最终渲染为终端用户看到的 UI。
3. 结构图(系统"由什么组成")
从架构与数据模型的维度,拆解设计语言系统的内部组成与模块关系。
3.1 包图 —— DLS 模块分层架构
设计语言系统通常遵循 Atomic Design 分层模型,从 Foundation(原子级的 Token)到 Component(分子/有机体级的 UI 单元),再到 Pattern(页面模板)。
Demo — 原子组件 → 分子组件 → 有机体组件:
// ------ Atoms: Token 驱动的原子组件 ------
// Button.tsx(仅依赖 token 变量)
import './button.css'; // 内部引用 var(--color-primary) 等 CSS 变量
export const Button = ({ variant = 'primary', children }) => (
<button className={`btn btn-${variant}`}>{children}</button>
);
// ------ Molecules: 组合原子 ------
// SearchBar.tsx(组合 Input + Button)
import { Input } from './Input';
import { Button } from './Button';
export const SearchBar = ({ onSearch }) => (
<div className="search-bar">
<Input placeholder="搜索..." />
<Button variant="primary">搜索</Button>
</div>
);
// ------ Organisms: 组合分子 ------
// PageHeader.tsx(组合 Logo + Nav + SearchBar + Avatar)
export const PageHeader = () => (
<header className="page-header">
<Logo />
<Nav items={navItems} />
<SearchBar onSearch={handleSearch} />
<Avatar />
</header>
);
3.2 组件图 —— DLS 系统整体拓扑
从工具链、Token 引擎、组件库到文档站与 CI/CD 管线的全链路架构。
3.3 类图 —— Design Token 与 Component 数据模型
设计语言系统中最核心的数据模型:DesignToken 承载原子级设计决策,Theme 组织多套 Token 集合,Component 引用 Token 进行渲染,Pattern 组合 Component 构建页面。
Demo — Token JSON 结构示例:
{
"global": {
"color": {
"blue": { "500": { "value": "#1677ff" } },
"red": { "500": { "value": "#ff4d4f" } },
"green": { "500": { "value": "#52c41a" } },
"gray": { "100": { "value": "#f5f5f5" }, "900": { "value": "#1f1f1f" } }
},
"spacing": {
"xs": { "value": "4px" },
"sm": { "value": "8px" },
"md": { "value": "16px" },
"lg": { "value": "24px" },
"xl": { "value": "32px" }
},
"radius": {
"sm": { "value": "4px" },
"md": { "value": "8px" },
"round": { "value": "9999px" }
}
},
"alias": {
"color": {
"primary": { "value": "{global.color.blue.500}" },
"danger": { "value": "{global.color.red.500}" },
"success": { "value": "{global.color.green.500}" },
"bg-base": { "value": "{global.color.gray.100}" },
"text-base": { "value": "{global.color.gray.900}" }
}
},
"component": {
"button": {
"padding-x": { "value": "{global.spacing.md}" },
"padding-y": { "value": "{global.spacing.sm}" },
"radius": { "value": "{global.radius.md}" },
"bg-primary": { "value": "{alias.color.primary}" }
}
}
}
4. 实战速查手册
4.1 主流设计系统对比
| 设计系统 | 出品方 | 核心框架 | Token 方案 | 适用场景 |
|---|---|---|---|---|
| Material Design 3 | Android / Flutter / Web | Design Token + M3 Tokens | 跨平台移动/Web 应用 | |
| Human Interface Guidelines | Apple | SwiftUI / UIKit | SF Symbols + Color Assets | iOS / macOS 原生应用 |
| Fluent 2 | Microsoft | React / WinUI | Fluent Tokens | M365 / Windows 生态 |
| Ant Design 5 | 蚂蚁集团 | React / Vue / Angular | CSS-in-JS + ConfigProvider | 企业级中后台 |
| Carbon | IBM | React / Svelte / Vue | Carbon Tokens | 企业 SaaS 产品 |
| Polaris | Shopify | React | Polaris Tokens | 电商管理后台 |
| Spectrum | Adobe | React / SwiftUI | Spectrum Tokens | 创意工具 / 企业应用 |
4.2 Design Token 设计速查
Token 三层架构(DTCG 规范):
- Global Tokens(全局层):原始设计值的唯一来源,如
blue-500: #1677ff - Alias Tokens(别名层):语义化引用 Global Token,如
color-primary → {blue-500} - Component Tokens(组件层):特定组件的设计决策,如
button-bg-primary → {color-primary}
| Token 类别 | 示例 Key | 示例 Value | CSS 变量 |
|---|---|---|---|
| 颜色 | color-brand-primary | #1677ff | --color-brand-primary |
| 间距 | spacing-md | 16px / 1rem | --spacing-md |
| 字号 | font-size-body | 14px / 0.875rem | --font-size-body |
| 字重 | font-weight-bold | 600 | --font-weight-bold |
| 圆角 | radius-md | 8px | --radius-md |
| 阴影 | shadow-card | 0 2px 8px rgba(0,0,0,0.1) | --shadow-card |
| 动效 | duration-fast | 150ms | --duration-fast |
| 断点 | breakpoint-md | 768px | --breakpoint-md |
4.3 Atomic Design 层级速查
Brad Frost 提出的 Atomic Design 方法论是大多数设计语言系统的思想基础:
| 层级 | 类比 | 含义 | Web 示例 |
|---|---|---|---|
| Atoms | 原子 | 不可再分的 UI 基础元素 | Button、Input、Icon、Label、Color |
| Molecules | 分子 | 多个原子组合成的功能单元 | SearchBar(Input + Button)、FormItem(Label + Input) |
| Organisms | 有机体 | 多个分子组成的独立区域 | PageHeader、Sidebar、ProductCard |
| Templates | 模板 | 有机体布局形成页面骨架 | 列表页模板、详情页模板 |
| Pages | 页面 | 模板填入真实内容后的最终产物 | 用户管理列表页、订单详情页 |
4.4 工具链速查
| 环节 | 工具 | 用途 |
|---|---|---|
| 设计工具 | Figma / Sketch | UI 设计、组件 Variant 管理、Token 预览 |
| Token 管理 | Style Dictionary / Tokens Studio | Token 定义、编译、多平台输出 |
| 组件开发 | Storybook / Ladle | 组件独立开发、可视化测试 |
| 文档站点 | Zeroheight / Docusaurus / Gatsby | 设计规范文档、使用指南 |
| 版本管理 | Git + Changesets | 组件版本控制、CHANGELOG 自动生成 |
| CI/CD | GitHub Actions / Chromatic | 自动构建、视觉回归测试、NPM 发布 |
| 质量保障 | Lighthouse / axe-core | 可访问性检测、性能审计 |
5. 实战演示
本章完整演示从整体布局设计 → Token 工程 → 组件开发 → 文档站搭建的全流程,以管理员后台(Admin Dashboard)为目标场景。
5.1 整体布局设计
设计任何 UI 的第一步永远是确定整体布局骨架。在动手写组件或 Token 之前,先回答三个问题:
- 信息架构(IA):页面有哪些区域?它们之间的主次关系是什么?
- 网格系统(Grid):用几列栅格?间距基准是多少?
- 响应式策略:不同屏幕宽度下布局如何变化?
示例场景:管理员后台 Dashboard
我们定义如下页面区域:
布局 Token(Layout Tokens)—— 在 tokens/layout.json 中定义:
{
"layout": {
"sidebar": { "width": { "value": "240px" }, "collapsed": { "value": "64px" } },
"header": { "height": { "value": "56px" } },
"content": { "max-width": { "value": "1280px" } }
},
"grid": {
"columns": { "value": 12 },
"gutter": { "value": "16px" },
"margin": { "value": "24px" }
},
"breakpoint": {
"xs": { "value": "0" },
"sm": { "value": "576px" },
"md": { "value": "768px" },
"lg": { "value": "992px" },
"xl": { "value": "1200px" },
"xxl":{ "value": "1600px" }
}
}
CSS 栅格系统实现 grid.css:
:root {
--grid-columns: 12;
--grid-gutter: 16px;
--grid-margin: 24px;
}
.ds-grid {
display: grid;
grid-template-columns: repeat(var(--grid-columns), 1fr);
gap: var(--grid-gutter);
padding: 0 var(--grid-margin);
}
.ds-col-4 { grid-column: span 4; }
.ds-col-6 { grid-column: span 6; }
.ds-col-8 { grid-column: span 8; }
.ds-col-12 { grid-column: span 12; }
/* 响应式 — 小屏时列堆叠 */
@media (max-width: 768px) {
.ds-grid { grid-template-columns: 1fr; }
.ds-col-4, .ds-col-6, .ds-col-8, .ds-col-12 {
grid-column: span 1;
}
}
页面布局骨架结构 DashboardLayout.tsx:
export const DashboardLayout = ({ children, collapsed }) => (
<div className="app-shell">
<aside className={`sidebar ${collapsed ? 'collapsed' : ''}`}>
<Logo />
<Nav items={menuItems} collapsed={collapsed} />
</aside>
<div className="main-area">
<header className="topbar">
<Breadcrumb />
<UserMenu />
</header>
<main className="content">
{children}
</main>
</div>
</div>
);
布局样式 layout.css(100% 引用 Token 变量):
.app-shell {
display: flex;
height: 100vh;
}
.sidebar {
width: var(--layout-sidebar-width);
background: var(--semantic-color-bg-subtle);
border-right: 1px solid var(--semantic-color-border);
transition: width var(--duration-normal, 0.2s);
flex-shrink: 0;
}
.sidebar.collapsed {
width: var(--layout-sidebar-collapsed);
}
.main-area {
flex: 1;
display: flex;
flex-direction: column;
min-width: 0;
}
.topbar {
height: var(--layout-header-height);
background: var(--semantic-color-bg-container);
border-bottom: 1px solid var(--semantic-color-border);
display: flex; align-items: center;
padding: 0 var(--spacing-lg);
justify-content: space-between;
flex-shrink: 0;
}
.content {
flex: 1;
overflow-y: auto;
padding: var(--spacing-xl);
max-width: var(--layout-content-max-width);
margin: 0 auto;
width: 100%;
}
@media (max-width: 768px) {
.sidebar { width: var(--layout-sidebar-collapsed); }
.content { padding: var(--spacing-md); }
}
5.2 搭建 Design Token 工程
目标:使用 Style Dictionary 将一份 Token JSON 源文件编译为 CSS 变量、SCSS 变量和 Swift 常量,实现「一次定义、多端输出」。
Step 1 — 初始化工程:
mkdir my-dls && cd my-dls
npm init -y
npm install style-dictionary --save-dev
Step 2 — 定义 Token 源文件 tokens/color.json:
{
"color": {
"brand": {
"primary": { "value": "#1677ff" },
"success": { "value": "#52c41a" },
"warning": { "value": "#faad14" },
"danger": { "value": "#ff4d4f" }
},
"neutral": {
"black": { "value": "#000000" },
"white": { "value": "#ffffff" },
"gray-100": { "value": "#f5f5f5" },
"gray-500": { "value": "#8c8c8c" },
"gray-900": { "value": "#1f1f1f" }
}
}
}
Step 3 — 定义语义化 Alias Token tokens/semantic.json:
{
"semantic": {
"color": {
"primary": { "value": "{color.brand.primary}" },
"success": { "value": "{color.brand.success}" },
"danger": { "value": "{color.brand.danger}" },
"bg-container": { "value": "{color.neutral.white}" },
"bg-subtle": { "value": "{color.neutral.gray-100}" },
"text-primary": { "value": "{color.neutral.gray-900}" },
"text-secondary":{ "value": "{color.neutral.gray-500}" }
}
}
}
Step 4 — 编写 Style Dictionary 配置文件 sd.config.js:
const StyleDictionary = require('style-dictionary');
StyleDictionary.extend({
source: ['tokens/**/*.json'],
platforms: {
css: {
transformGroup: 'css',
buildPath: 'dist/css/',
files: [
{ destination: 'tokens.css', format: 'css/variables' },
{
destination: 'tokens.json',
format: 'json/flat',
options: { outputReferences: true }
}
]
},
scss: {
transformGroup: 'scss',
buildPath: 'dist/scss/',
files: [
{ destination: '_tokens.scss', format: 'scss/variables' }
]
},
swift: {
transformGroup: 'ios-swift',
buildPath: 'dist/ios/',
files: [
{ destination: 'DSColor.swift', format: 'ios-swift/class.swift' }
]
}
}
}).buildAllPlatforms();
Step 5 — 执行构建并验证输出:
npx style-dictionary build --config sd.config.js
# 输出的 CSS 变量示例 (dist/css/tokens.css)
# --color-brand-primary: #1677ff;
# --semantic-color-primary: #1677ff;
# --semantic-color-bg-container: #ffffff;
5.3 构建主题化组件
目标:基于 Token CSS 变量构建一套 React 组件(Button / Card / Notification),支持亮色/暗色主题一键切换。
Step 1 — 定义暗色主题 Token tokens/dark-theme.json:
{
"semantic": {
"color": {
"bg-container": { "value": "{color.neutral.gray-900}" },
"bg-subtle": { "value": "#2a2a2a" },
"text-primary": { "value": "{color.neutral.white}" },
"text-secondary":{ "value": "#a0a0a0" }
}
}
}
Step 2 — 在 sd.config.js 中新增暗色主题构建平台:
// 在 platforms 中追加:
cssDark: {
transformGroup: 'css',
buildPath: 'dist/css/',
files: [
{
destination: 'tokens-dark.css',
format: 'css/variables',
filter: (token) => token.filePath.includes('dark-theme')
}
]
}
Step 3 — 编写主题切换 Hook useTheme.ts:
import { useState, useEffect } from 'react';
type Theme = 'light' | 'dark';
const STORAGE_KEY = 'app-theme';
export function useTheme() {
const [theme, setTheme] = useState<Theme>(() => {
const stored = localStorage.getItem(STORAGE_KEY);
if (stored === 'light' || stored === 'dark') return stored;
return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';
});
useEffect(() => {
localStorage.setItem(STORAGE_KEY, theme);
}, [theme]);
const toggle = () => setTheme(t => t === 'light' ? 'dark' : 'light');
return { theme, toggle };
}
Step 4 — 实现 Button 组件 Button.tsx:
import React from 'react';
import './Button.css';
interface ButtonProps {
variant?: 'primary' | 'secondary' | 'danger';
size?: 'sm' | 'md' | 'lg';
disabled?: boolean;
loading?: boolean;
children: React.ReactNode;
onClick?: () => void;
}
export const Button: React.FC<ButtonProps> = ({
variant = 'primary', size = 'md',
disabled = false, loading = false,
children, onClick
}) => (
<button
className={`ds-btn ds-btn--${variant} ds-btn--${size}`}
disabled={disabled || loading}
onClick={onClick}
>
{loading && <span className="ds-btn__spinner" />}
{children}
</button>
);
Step 5 — Button 样式 Button.css(全部引用 Token 变量):
.ds-btn {
display: inline-flex;
align-items: center;
gap: 6px;
font-family: inherit;
font-size: var(--font-size-body, 14px);
font-weight: var(--font-weight-medium, 500);
border: 1px solid transparent;
border-radius: var(--radius-md, 6px);
cursor: pointer;
transition: background var(--duration-fast, 0.15s),
box-shadow var(--duration-fast, 0.15s);
}
.ds-btn--sm { padding: 4px 12px; font-size: 12px; }
.ds-btn--md { padding: 8px 16px; }
.ds-btn--lg { padding: 12px 24px; font-size: 16px; }
.ds-btn--primary {
color: #fff;
background: var(--semantic-color-primary, #1677ff);
}
.ds-btn--primary:hover:not(:disabled) {
background: var(--color-brand-primary-hover, #4096ff);
}
.ds-btn--primary:active:not(:disabled) {
background: var(--color-brand-primary-active, #0958d9);
}
.ds-btn--secondary {
color: var(--semantic-color-text-primary);
background: var(--semantic-color-bg-container);
border-color: var(--color-neutral-gray-300, #d9d9d9);
}
.ds-btn--secondary:hover:not(:disabled) {
color: var(--semantic-color-primary);
border-color: var(--semantic-color-primary);
}
.ds-btn--danger {
color: #fff;
background: var(--semantic-color-danger, #ff4d4f);
}
.ds-btn:disabled {
opacity: 0.45;
cursor: not-allowed;
}
.ds-btn__spinner {
width: 14px; height: 14px;
border: 2px solid transparent;
border-top-color: currentColor;
border-radius: 50%;
animation: ds-spin 0.6s linear infinite;
}
@keyframes ds-spin { to { transform: rotate(360deg); } }
Step 6 — 主题注入 App.tsx:
import { useTheme } from './useTheme';
import { Button } from './components/Button';
function App() {
const { theme, toggle } = useTheme();
return (
<div className={`app app--${theme}`}>
<header style={{ display:'flex', justifyContent:'space-between',
padding:16, background:'var(--semantic-color-bg-subtle)' }}>
<h1 style={{ color:'var(--semantic-color-text-primary)' }}>My DLS</h1>
<Button variant="secondary" size="sm" onClick={toggle}>
{theme === 'light' ? '🌙 暗色' : '☀️ 亮色'}
</Button>
</header>
<main style={{ padding: 24 }}>
<Button variant="primary">主按钮</Button>
<Button variant="secondary">次按钮</Button>
<Button variant="danger">危险按钮</Button>
<Button variant="primary" loading>加载中</Button>
<Button variant="primary" disabled>禁用</Button>
</main>
</div>
);
}
5.4 搭建 Storybook 组件文档
目标:为上面的 Button 组件搭建 Storybook 文档站,实现组件的可视化开发、交互测试和自动文档生成。
Step 1 — 安装 Storybook:
npx storybook@latest init --type react
npm install @storybook/addon-essentials --save-dev
Step 2 — 配置 Token 注入 .storybook/preview.ts:
import type { Preview } from '@storybook/react';
import '../dist/css/tokens.css'; // 全局注入 Token CSS 变量
const preview: Preview = {
parameters: {
backgrounds: {
default: 'light',
values: [
{ name: 'light', value: '#ffffff' },
{ name: 'dark', value: '#1f1f1f' }
]
},
controls: { matchers: { color: /background|color$/i } }
}
};
export default preview;
Step 3 — 编写 Button Story src/stories/Button.stories.tsx:
import type { Meta, StoryObj } from '@storybook/react';
import { Button } from '../components/Button';
const meta: Meta<typeof Button> = {
title: 'Components/Button',
component: Button,
argTypes: {
variant: { control:'select', options:['primary','secondary','danger'] },
size: { control:'select', options:['sm','md','lg'] },
loading: { control:'boolean' },
disabled:{ control:'boolean' },
onClick: { action:'clicked' }
}
};
export default meta;
type Story = StoryObj<typeof Button>;
export const Primary: Story = { args: { variant:'primary', children:'主按钮' } };
export const Secondary: Story = { args: { variant:'secondary', children:'次按钮' } };
export const Danger: Story = { args: { variant:'danger', children:'危险按钮' } };
export const Loading: Story = { args: { variant:'primary', loading:true, children:'加载中' } };
export const Disabled: Story = { args: { variant:'primary', disabled:true, children:'禁用' } };
export const Sizes: Story = {
render: () => (
<div style={{ display:'flex', gap:8, alignItems:'center' }}>
<Button size="sm">小号</Button>
<Button size="md">中号</Button>
<Button size="lg">大号</Button>
</div>
)
};
Step 4 — 启动 Storybook:
npm run storybook
# 访问 http://localhost:6006 即可查看 Button 组件文档
| Storybook 页面 | 功能 |
|---|---|
| Controls 面板 | 动态切换 variant / size / disabled 等 Props,实时预览组件变化 |
| Actions 面板 | 捕获 onClick 事件,验证交互回调 |
| Backgrounds 面板 | 切换亮/暗背景,验证组件在两种主题下的视觉效果 |
| Docs 页面 | 自动生成 Props 表格、代码示例、组件描述 |
6. 高颜值动效设计方法论
前面几章讲「设计语言系统如何搭建」,本章回答另一个问题:为什么有的页面一眼就「炫酷高级」,有的堆满特效却廉价?以 MotionSites / Awwwards 系高颜值 3D 动效落地页为研究对象,提炼出一套可复制的设计方法论——不是堆特效,而是用一套系统化手法把「注意力 + 技术信号」做出来。
6.1 设计与技术栈的两层关系
先说清一个常见误区:「设计跟技术栈没关系」这句话要拆成两层看——设计的内容无关,设计的实现高度相关。
| 层面 | 是否与技术栈有关 | 说明 |
|---|---|---|
| 设计内容 (规范 / 语言) | 无关 | 色彩、间距、字体、动效 Token、栅格是抽象标准,同一套可落地到 React / Vue / SwiftUI / Compose / Figma——这正是 DLS + Style Dictionary 的价值 |
| 设计实现 (边界 / 成本) | 高度相关 | 技术栈与浏览器能力划定了「设计可行域」:backdrop-filter、3D transform、GPU 合成、WebGL 粒子能否实现、成本多高 |
关于「UI 库不是都带了样式吗」:UI 库带的样式是预制默认值,是「设计的一种实现快照」,不是设计本身,更不是设计上限——
| 层面 | 决定什么 | 谁说了算 |
|---|---|---|
| UI 库默认样式 | 下限(及格线) | 库作者 |
| Design Tokens 覆盖 | 换主题 / 换观感 | 你 |
| 设计规范 | 上限(审美品位) | 你 |
同一个 shadcn/ui,换一套 Tokens 既可做成 Stripe 风、也可做成暗黑赛博风——库的样式只是起点。
6.2 设计语言本质 — 颜值为什么值钱
高颜值设计本质上是 注意力经济 + 技术信号 的复合产物:
| 机制 | 本质 | 对用户的作用 |
|---|---|---|
| 注意力经济 | 信息过载时代,视觉是第一印象过滤层 | 先抓住眼球,用户才愿意继续看 |
| 技术信任信号 | 3D / 动效 / 粒子 = 「我们技术很强」的潜台词 | 对产品能力产生先入为主的信任 |
| Aesthetic-Usability Effect | 好看的界面被认为「更好用」 | 降低决策摩擦,容忍小瑕疵 |
| 社交货币 | 高颜值页面用户更愿意截图 / 分享 | 自传播,降低获客成本 |
| 差异化壁垒 | AI 生成内容同质化,视觉是最后非价格竞争维度 | 与同质化竞品拉开差距 |
6.3 五大方法论支柱
支柱一:Aesthetic-Usability 驱动(视觉优先)
- Depth layering(前景 / 中景 / 背景分离)制造空间感。
- Glassmorphism / 渐变弥散光作为基础质感层。
- 动效不是装饰,而是导航线索(滚动视差 = 「还有更多内容」)。
支柱二:Motion Design as a System(动效是一个系统,不是堆特效)
- 统一缓动:全局一致 ease-out(如
cubic-bezier(0.4,0,0.2,1)),不用 linear。 - Stagger 错峰:元素依次进场,制造「精致编排感」。
- 滚动叙事:滚动驱动内容 Reveal,而非点击跳转(Apple 产品页范式)。
- 时长规范:微交互约 150ms,转场 300–600ms,过长显拖沓。
支柱三:3D 氛围策略(3D 是氛围层,不是内容层)
- 3D 用做背景氛围(粒子 / 浮动几何体),不干扰正文可读性。
- 鼠标跟踪 / 视差绑定交互,制造「临场感」。
- 铁律:内容永远在 3D 之上,必须清晰可读。
支柱四:色彩与光影体系
| 手法 | 做法 | 效果 |
|---|---|---|
| Dark mode first | 深色背景打底 | 3D 发光 / 粒子更突出 |
| Gradient 替代纯色 | 弥散光 / 渐变背景 | 比纯色更有质感 |
| Accent glow | 关键元素加发光 / 辉光 | 焦点引导 |
| 克制用色 | 1 主色 + 1 强调色 + 中性灰阶 | 高级感来自克制 |
支柱五:滚动叙事(Scroll-triggered storytelling)
以滚动为时间轴,把整页组织成一个「逐段展开的故事」。每个 Section 由一个滚动锚点驱动其内部动效,形成「读到哪、动到哪」的沉浸体验。
6.4 工具链方法
| 层 | 工具 | 职责 |
|---|---|---|
| 动效编排 | GSAP + ScrollTrigger | 时间轴、滚动触发、错峰 |
| 3D 渲染 | Three.js / React Three Fiber | 背景 3D、粒子、视差 |
| 视觉效果 | CSS filter / backdrop-filter / canvas | 辉光、玻璃拟态、粒子 |
| 性能保障 | 只动 transform / opacity + will-change | 60fps 保底 |
6.5 反向工程案例 — 把设计语言拆成 Prompt
MotionSites 这类产品本质是 把「审美溢价」做成可复制的商品:将高颜值页面的设计语言拆成四层,再写成 AI 能理解的 Prompt,一键生成。
| 层 | 拆什么 | Prompt 描述示例 |
|---|---|---|
| 布局结构 | Section 顺序与内容 | 「Hero → 特性 → 3D 展示 → 定价 → CTA」 |
| 动效参数 | 滚动到哪触发什么、缓动 / 错峰 | 「滚动进入时特性卡片 stagger 上浮,0.6s ease-out」 |
| 色彩光影 | 渐变值、透明度、辉光 | 「深空黑底 + 靛紫渐变辉光 + 关键元素 glow」 |
| 3D 资产 | 粒子数量 / 旋转 / 颜色 | 「背景漂浮几何体,随鼠标视差移动,透明 0.4」 |
# 一份可复制的落地页 Prompt 模板(结构化)
主题:SaaS AI 产品 Landing Page
布局:Hero(超大标题 + 3D 背景)→ 特性(stagger 进场)→ 定价 → CTA
动效:滚动叙事;特性卡片 0.6s ease-out 错峰上浮;CTA 磁吸辉光
色彩:深空黑底(#0a0a14) + 靛紫渐变(#6366f1→#a855f7) + 白色文字
3D :背景粒子 + 浮动几何体,鼠标视差,透明 0.4,缓慢自转
性能:全部 transform/opacity 动画,prefers-reduced-motion 降级
6.6 资源库速查 — 直接复制成功设计
日常做高颜值页面,优先复制而非从零设计:从灵感库挑参考 → 抄现成组件 / Prompt → 让 AI 拼装,几乎不用手写样式。以下是经核实的主流资源入口。
① AI 提示词类(同 MotionSites 赛道,复制 Prompt 即可)
| 站点 | 收费 | 特点 |
|---|---|---|
| motionsites.ai | 免费/订阅 | 落地页 prompt,复制后贴进 Lovable / Bolt / Cursor / Claude 即可出站 |
| 21st.dev | 免费+会员 | 12000+ 组件/模板/主题,每个都做成 prompt,贴进 Cursor/Claude Code/v0/Lovable 自动落进仓库;免费每天 2 次 |
② Copy-Paste 组件 / 区块库(直接抄代码,最实用)
| 站点 | 规模 | 收费 | 特点 |
|---|---|---|---|
| ui.aceternity.com | 200+ 组件/blocks | 免费+Pro | React + Tailwind + Motion,高颜值动效(3D card、bento、globe、sparkles) |
| magicui.design | 150+ 组件 | 开源免费 | shadcn 配套动效组件,GitHub 开源 |
| shadcnblocks.com | 1837 blocks | 免费+Pro | shadcn/ui 生态最大块库,Hero/Feature/Pricing 全场景,CLI 一键装 |
| reactbits.dev | 大量动效组件 | 免费 | 动画组件集,直接复制 |
| originui.com | 508 components | 开源免费 | Base UI 之上的现代组件库 |
| uiverse.io | 数千个 | 免费 | 纯 CSS/HTML 元素(按钮、卡片、loading),免登录复制 |
③ 灵感 + 可直接拆的落地页
| 站点 | 用途 |
|---|---|
| landingfolio.com | 精品落地页灵感库(按行业/颜色筛选)+ 791 个可复制组件 |
| awwwards.com | 顶级动效站点风向标 |
| lapa.ninja | 落地页设计精选 |
| godly.website | 高颜值网页灵感 |
| framer.com/templates | 官方模板库,可在 Framer 里直接 clone |
④ 直接扒站工具(真正的"复制成功设计")
| 工具 | 用途 |
|---|---|
| getdesign.ai | 一键把任意网页复制成组件,进 Lovable / Claude / Cursor |
| Framer | 可 clone 任意公开 Framer 站点 |
| Chrome 扒站插件 | 抓取任意站点 HTML / CSS / JS(如 SingleFile 等) |